#include "graphic_image_loader_tga.h"
/*--------------------------------------------------------------------------------*/
#include "input_file_manager.h"
/*--------------------------------------------------------------------------------*/
#pragma pack(push, 1)
struct TGA_HEADER
{
    UBYTE
		LengthId,
		ColorMapType,
		ImageType;
    SHORT
		CMFirstEntry,
		CMLength;
    UBYTE
		CMSize;
    SHORT
		XOrigin,
		YOrigin,
		Width,
		Height;
    UBYTE
		PixelDepth,
		ImageDescriptor;
};
#pragma pack(pop)
/*--------------------------------------------------------------------------------*/
GRAPHIC_IMAGE::REF GRAPHIC_IMAGE_LOADER_TGA::LoadFromFile( const TEXT & file_name )
{
	TGA_HEADER
		Header;
	INPUT_FILE::REF
		file;
	GRAPHIC_IMAGE::REF
		image;
	INDEX
		index;
	COUNT
		byte_count;
	UBYTE
		color[4];

	file = INPUT_FILE_MANAGER_GetFile( file_name + ".tga" );

	if ( file->Open() )
	{
		Header = file->Read< TGA_HEADER >();
		image.New();
		image->SetHeight( Header.Height );
		image->SetWidth( Header.Width );

		switch( Header.ImageType )
		{
			case 2: // BGR uncompressed
			{
				switch ( Header.PixelDepth )
				{
					case 32:
					{
						image->SetFormat( GRAPHIC_IMAGE_FORMAT_Rgba );
						image->SetBytesPerPixel( 4 );

						byte_count = Header.Width * Header.Height * 4;

						for_each_index( index, byte_count )
						{
							file->ReadBuffer( &color[0], 4 );
							image->AddByte( color[2] );
							image->AddByte( color[1] );
							image->AddByte( color[0] );
							//image->AddByte( color[3] );
							image->AddByte( 255 );
						}
					}
					break;

					case 24:
					{
						image->SetFormat( GRAPHIC_IMAGE_FORMAT_Rgb );
						image->SetBytesPerPixel( 3 );

						byte_count = Header.Width * Header.Height * 3;

						for_each_index( index, byte_count )
						{
							file->ReadBuffer( &color[0], 3 );
							image->AddByte( color[2] );
							image->AddByte( color[1] );
							image->AddByte( color[0] );
						}
					}
					break;


				}
			}
			break;

			case 9: // 8bits indexed colors
			{
				DEBUG_Break( "TODO" );
			}
			break;

			case 10: // BGR RLE-compressed
			{
				switch ( Header.PixelDepth )
				{
					case 32:
					{
						UBYTE
							header_byte;
						COUNT
							sub_size;
						INDEX
							sub_index;

						image->SetFormat( GRAPHIC_IMAGE_FORMAT_Rgba );
						image->SetBytesPerPixel( 4 );

						byte_count = Header.Width * Header.Height * 4;

						index = 0;

						while( index < byte_count )
						{
							file->Read< UBYTE >( header_byte );
							sub_size = 1 + ( header_byte & 0x7f );

							if( header_byte & 0x80 )
							{
								file->ReadBuffer( &color[0], 4 );

								for_each_index( sub_index, sub_size )
								{
									image->AddByte( color[2] );
									image->AddByte( color[1] );
									image->AddByte( color[0] );
									image->AddByte( color[3] );
								}
							}
							else
							{
								for_each_index( sub_index, sub_size )
								{
									file->ReadBuffer( &color[0], 4 );
									image->AddByte( color[2] );
									image->AddByte( color[1] );
									image->AddByte( color[0] );
									image->AddByte( color[3] );
								}
							}

							index += sub_size * 4;
						}
					}
					break;

					case 24:
					{
						UBYTE
							header_byte;
						COUNT
							sub_size;
						INDEX
							sub_index;

						image->SetFormat( GRAPHIC_IMAGE_FORMAT_Rgb );
						image->SetBytesPerPixel( 3 );

						byte_count = Header.Width * Header.Height * 3;

						index = 0;

						while( index < byte_count )
						{
							file->Read< UBYTE >( header_byte );
							sub_size = 1 + ( header_byte & 0x7f );

							if( header_byte & 0x80 )
							{
								file->ReadBuffer( &color[0], 3 );

								for_each_index( sub_index, sub_size )
								{
									image->AddByte( color[2] );
									image->AddByte( color[1] );
									image->AddByte( color[0] );
								}
							}
							else
							{
								for_each_index( sub_index, sub_size )
								{
									file->ReadBuffer( &color[0], 3 );
									image->AddByte( color[2] );
									image->AddByte( color[1] );
									image->AddByte( color[0] );
								}
							}

							index += sub_size * 3;
						}
					}
					break;

					default:
					{
						DEBUG_Break( "Unsupported format" );
					}
					break;
				}
			}
			break;

			default:
			{
				DEBUG_Break( "Unsupported format" );
			}
			break;
		}

		file->Close();

		if( ( Header.ImageDescriptor & 0x20 ) )
		{
			image->VerticalFlip();
		}
	}

	DEBUG_Log( "Image \"" + file_name + "\" " );
	DEBUG_Log( Header.Width );
	DEBUG_Log( "x" );
	DEBUG_Log( Header.Height );
	DEBUG_LogLine( " loaded." );

	return image;
}
/*--------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------*/

